#! /usr/bin/perl -w

use Cwd;
use warnings;
use strict;
use Term::ANSIColor;
use File::Compare;

sub print_head(){    #Color head of test suit
print"**********************************************\n";
print"**********-------------------------***********\n";
print"**********          FIND           ***********\n";
print"**********     TEST      SUIT      ***********\n";
print"**********-------------------------***********\n";
print"**********************************************\n";
}

sub print_ok(){
    print"\n=================================>[";
    print color 'bold green';
    print(" SUCCESS ");
    print color 'reset';
    print"]\n";
}

sub print_ko(){
    print"\n=================================>[";
    print color 'bold red';
    print(" FAIL ");
    print color 'reset';
    print "]\n";
}

sub exec_test (){
    my @args = @_;
    my @tablo = split(/.tst/, $_[4]);
    my $ret = -1;
    my $line = "";
    my $error = "";
    $ret = system ("echo '$_[2]' | $_[0] 2> $tablo[0].out 1>> $tablo[0].out");
    system("echo '$_[2]' | bash --posix 2> $tablo[0].bout 1>> $tablo[0].bout");
    $ret = $ret % 255;
    $error = &parsebout("$tablo[0].bout");
    if (($_[1] == 1) && ($ret == $_[1])) {
	if (($error eq $_[3]) == 0){
	    &print_ok();
	    return 0;
	}
	else {
	    &print_ko();
	    return 1;
	}
    }
    else{
	if (($ret == $_[1]) && (compare("$tablo[0].out", "$tablo[0].bout") == 0)) {
	    &print_ok();
	    return 0;
	} else {
	    &print_ko();
	    return 1;
	}
    }
}


sub exec_test2(){
       my @args = @_;
       my @test = split(/.test/, $_[4]);
       my $ret = -1;
       my $error = "";
       $ret = system ("$_[0] $_[2] 2> $test[0].out 1>> $test[0].out");
       system("find $_[2] 2> $test[0].bout 1>> $test[0].bout");
       $ret = $ret % 255;
       $error = &parsebout("$test[0].bout");
    if (($_[1] == 1) && ($ret == $_[1])) {
	if (($error eq $_[3]) == 0){
	    return 0;
	}
	else {
	    return 1;
	}
    }
    else{
	if (($ret == $_[1]) && (compare("$test[0].out", "$test[0].bout") == 0)) {
	    return 0;
	} else {
	    return 1;
	}
    }
}


sub parsebout(){
    my @args = @_;
    my $basherr = "";
    my $line = "";
    my $result = "";
    if ((-f $_[0]) && ($_[0] =~ m/^(.+).bout$/)){
	open(FD, $_[0]) || die ("can't open $_[0]");
	while ($line = <FD>){
	    $result = $line;
	    if ($result =~ m/^bash:(.+)\n$/){
		my @bashtab = split (/:/, $result);
		@bashtab = reverse(@bashtab);
		$basherr = $bashtab[0];
		return $basherr;
	    }
	}
    }
}

sub test(){
    my @args = @_;
    my $retValue = "";
    my $param = "";
    my $cmd = "";
    my $line = "";
    my $stderr = "";
    my $result = "";
    my $ret = 0;
    my $aux = 0;

    $aux =  &option($ARGV[0], $ARGV[1]);
    if ((-f $_[0]) && ($_[0] =~ m/^(.+).tst$/)){
	open(FD, $_[0]) || die ("can't open $_[0]");
	while ($line = <FD>){
	    $result = $line;
	    if ($result =~ m/^#cmd:(.+)\n$/){
		my @tmp = split (/:/, $result);
		my $aux = $tmp[1];
		my @tmp2 = split(/\n/, $aux);
		$cmd = $tmp2[0];
	    }
	    if ($result =~ m/^#return:(.+)\n$/){
		my @tmp = split(/:/, $result);
		$retValue = $tmp[1];
	    }
	    if ($result =~ m/^#param:(.+)\n$/){
		my @tmp = split(/:/, $result);
		my $aux = $tmp[1];
		my @tmp2 = split(/\n/, $aux);
		$param = $tmp2[0];
	    }
	    if ($result =~ m/^#stderr:(.+)\n$/){
		my @tmp = split(/:/, $result);
		my $aux = $tmp[1];
		my @tmp2 = split(/\n/, $aux);
		$stderr = $tmp2[0];
	    }
	}

	if (($aux == 0) || ($aux == 2)){
	      print ("\t\tTest $param in $_[1] : ");
	    $ret = &exec_test($cmd, $retValue, $param, $stderr, $_[0]);

	} else {

	     $ret = &exec_test2($cmd, $retValue, $param,$stderr, $_[0]);

	}
	close(FD);
	return $ret;
	}
    return (-1);
    }

sub make_ratio(){
        my @args = @_;
	my $percent = 0;
	my $success = 0;
	my $troisquart = 0;
	my $moitie = 0;
	my $macolor = '';

	$success = $_[0] - $_[1];
	$moitie = int($_[0] / 2);
	$troisquart = int($_[0] * 0.75);
	if (($success < $troisquart) && ($success > $moitie)){
	    $macolor = ' bold yellow';
	} elsif ($success < $moitie) {
	    $macolor = 'bold red';
	} else {
	    $macolor = 'bold green';
	}
	print("\t\t\tThe program pass: ");
	print color $macolor;
	print "$success";
	print color 'reset';
	print ("/$_[0] tests\n");
}



sub make_percent()
{
    my @args = @_;
    my $percent = 0;
    my $success = 0;
    my $macolor = '';
    $success = $_[0] - $_[1];

    $percent = int((100*$success) / $_[0]);
    if (($percent < 95) && ($percent > 80)){
	$macolor = ' bold yellow';
    } elsif ($percent <80) {
	$macolor = 'bold red';
    } else {
	$macolor = 'bold green';
    }
    print("\t\t\tThe program pass: ");
    print color $macolor;
    print $percent."%";
    print color 'reset';
    print(" of the tests\n");
}
sub category (){
    my @args = @_;
    my $nbrTest = 0;
    my $nbrFail = 0;
    my $ret = 0;
    my $aux = &option($ARGV[0], $ARGV[1]);
    my $testPath = "";
    opendir(DIR, $_[0]) || die ("Can't open $_[0] it isn't a directory\n") ;
    my @listTest = readdir(DIR);
         if (($aux != 3) && ($aux != 4)){
	     print ("\tEnter in the  category\t" . $_[1] . "\n");

	 }
    foreach my $testFile (@listTest){
	$testPath = $_[0]. "/" .$testFile;
	if ((-f $testPath) && ($testPath =~ m/^(.+).tst$/)){
		$ret = &test($testPath, $testFile);
		$nbrTest++;
		$nbrFail = $nbrFail - $ret;
	}
    }
    $nbrFail = -$nbrFail;
    my $tmp = $nbrTest - $nbrFail;
    my @tab_value = ($nbrTest, $nbrFail);
    if ($aux == 1){
	&make_percent ($nbrTest, $nbrFail);
    } elsif ((($aux == 0) || ($aux == 2))){
	&make_percent ($nbrTest, $nbrFail);
	&make_ratio($nbrTest, $nbrFail);
    }
    if (($aux != 3) && ($aux != 4)){
	print "\t The category $_[1] is over \n\n\n";
    }
    return @tab_value;
}

sub option(){
    my $opt ="";

    if ($#ARGV == -1){
	$opt = "";
    } else {
	$opt = $ARGV[0];
    }

    if (($opt eq "-a") || ($opt eq "-all") ||($opt eq "")){
	return 0;
    } elsif (($opt eq "-c") || ($opt eq "-categories")){
	return 1;
    } elsif (($opt eq "-e") || ($opt eq "-select")){
	return 2;
    } elsif (($opt eq "-f") || ($opt eq "-final")){
	return 3;
    } elsif (($opt eq "-n") || ($opt eq "-number")){
	return 4;
    } else {
	die ("This $ARGV[0] isn't a valid option.");
    }
}


sub main(){


    my $curDir = getcwd;
    my $catDir = "";
    my $catPath = "";
    my $_=0;
    my @tab_val= ();
    my $opt = &option($ARGV[0], $ARGV[1]);
    my $test = 0;
    my $fail =0;

    &print_head();
    opendir(IMD, $curDir) || die ("Can't open directories");
    my @listDir =  readdir(IMD);

    $catPath = $curDir . $catDir;
    if ($opt == 2){
	for (my $i = 1; $i <= $#ARGV; $i++)  {
	    $catPath = $curDir."/".$ARGV[$i];
	    @tab_val = &category($catPath, $ARGV[$i]);
	    $test = $test + $tab_val[0];
	    $fail = $fail + $tab_val[1];
	}
    }else{
	foreach my $catDir (@listDir){
	    if (-d $catDir){
		if (($catDir =~ m/^\.(.+)$/) || ($catDir =~ m/^\.$/) || ($catDir =~ m/^\.\.$/)){
		}else{
		    $catPath = $curDir ."/". $catDir;
		    @tab_val = &category($catPath, $catDir);
		    $test = $test + $tab_val[0];
		    $fail = $fail + $tab_val[1];
		}
	    }
	}
    }
    if (($opt == 3) || ($opt == 0)){
	&make_percent($test, $fail);
    }
    if (($opt == 4) || ($opt == 0)){
	&make_ratio($test, $fail);
	}
    print color 'bold cyan';
    print("\tThe testing suit finished \n\n");
    print color 'reset';
    closedir(IMD);
    return (1);
}
main ();

